"""
RS232 Interface

实现基于串口的RS232通信接口
"""

import serial
import threading
import time
from typing import Optional
from .base import RadarInterface
from ..exceptions import RadarConnectionError, RadarTimeoutError


class RS232Interface(RadarInterface):
    """RS232串口通信接口"""

    def __init__(self, config: dict):
        super().__init__(config)
        self.port = config.get('port', 'COM1')
        self.baud_rate = config.get('baud_rate', 115200)
        self.data_bits = config.get('data_bits', 8)
        self.stop_bits = config.get('stop_bits', 1)
        self.parity = config.get('parity', 'N')
        self.flow_control = config.get('flow_control', 'none')
        self.serial_port: Optional[serial.Serial] = None
        self._receive_thread: Optional[threading.Thread] = None
        self._stop_receiving = False
        self._buffer = bytearray()

    def connect(self) -> None:
        """连接到雷达设备"""
        try:
            # 配置串口参数
            parity_map = {'none': 'N', 'odd': 'O', 'even': 'E'}
            flow_control_map = {
                'none': 0,
                'hardware': serial.RTSCTS,
                'software': serial.XONXOFF
            }

            self.serial_port = serial.Serial(
                port=self.port,
                baudrate=self.baud_rate,
                bytesize=self.data_bits,
                stopbits=self.stop_bits,
                parity=parity_map.get(self.parity, 'N'),
                xonxoff=flow_control_map.get(self.flow_control, 0),
                timeout=self.timeout / 1000
            )

            self.is_connected = True
            self._start_receiving()

        except serial.SerialException as e:
            self.disconnect()
            raise RadarConnectionError(f"连接到 {self.port} 失败: {e}")

    def disconnect(self) -> None:
        """断开与雷达设备的连接"""
        self._stop_receiving = True
        self.is_connected = False

        if self._receive_thread and self._receive_thread.is_alive():
            self._receive_thread.join(timeout=2)

        if self.serial_port:
            self.serial_port.close()
            self.serial_port = None

    def send_data(self, data: bytes) -> None:
        """发送数据到雷达设备"""
        if not self.is_connected or not self.serial_port:
            raise RadarConnectionError("未连接到雷达设备")

        try:
            bytes_written = self.serial_port.write(data)
            if bytes_written != len(data):
                raise RadarConnectionError("数据发送不完整")
        except serial.SerialException as e:
            raise RadarConnectionError(f"发送数据失败: {e}")

    def receive_data(self, timeout: Optional[int] = None) -> bytes:
        """从雷达设备接收数据"""
        if not self.is_connected or not self.serial_port:
            raise RadarConnectionError("未连接到雷达设备")

        try:
            old_timeout = self.serial_port.timeout
            if timeout is not None:
                self.serial_port.timeout = timeout / 1000

            # 查找起始符
            start_marker = b'\xAA'  # 假设起始符为0xAA
            data = bytearray()

            # 等待起始符
            while True:
                byte = self.serial_port.read(1)
                if not byte:
                    raise RadarTimeoutError("接收数据超时")
                if byte == start_marker:
                    data.extend(byte)
                    break

            # 读取剩余数据
            while len(data) < 8:  # 最小帧长度
                byte = self.serial_port.read(1)
                if not byte:
                    raise RadarTimeoutError("接收数据超时")
                data.extend(byte)

            # 解析数据长度（第4-5字节为数据长度）
            data_length = int.from_bytes(data[3:5], byteorder='big')
            total_length = 8 + data_length  # 总长度 = 头部长度 + 数据长度

            # 读取剩余数据
            while len(data) < total_length:
                byte = self.serial_port.read(1)
                if not byte:
                    raise RadarTimeoutError("接收数据超时")
                data.extend(byte)

            return bytes(data)

        except serial.SerialException as e:
            raise RadarConnectionError(f"接收数据失败: {e}")
        finally:
            if timeout is not None:
                self.serial_port.timeout = old_timeout

    def send_command(self, command: bytes, timeout: Optional[int] = None) -> bytes:
        """发送命令并等待响应"""
        if not self.is_connected or not self.serial_port:
            raise RadarConnectionError("未连接到雷达设备")

        try:
            # 发送命令
            self.send_data(command)

            # 等待响应
            old_timeout = self.serial_port.timeout
            if timeout is not None:
                self.serial_port.timeout = timeout / 1000

            response = self.serial_port.read(4096)
            return response

        except serial.SerialException as e:
            raise RadarConnectionError(f"命令执行失败: {e}")
        finally:
            if timeout is not None:
                self.serial_port.timeout = old_timeout

    def _start_receiving(self) -> None:
        """启动数据接收线程"""
        self._stop_receiving = False
        self._receive_thread = threading.Thread(target=self._receive_loop, daemon=True)
        self._receive_thread.start()

    def _receive_loop(self) -> None:
        """数据接收循环"""
        while not self._stop_receiving and self.is_connected:
            try:
                if self.serial_port:
                    # 非阻塞读取
                    self.serial_port.timeout = 0.1
                    try:
                        byte = self.serial_port.read(1)
                        if byte:
                            self._buffer.extend(byte)
                            # 检查是否接收到完整的数据包
                            self._process_buffer()
                    except:
                        continue
            except Exception as e:
                if not self._stop_receiving:
                    print(f"接收线程错误: {e}")
                break

    def _process_buffer(self) -> None:
        """处理接收缓冲区"""
        # 查找起始符
        start_marker = b'\xAA'
        start_pos = self._buffer.find(start_marker)

        if start_pos == -1:
            # 没有找到起始符，清空缓冲区
            self._buffer.clear()
            return

        # 移除起始符之前的数据
        if start_pos > 0:
            del self._buffer[:start_pos]

        # 检查是否接收到足够的数据
        if len(self._buffer) < 8:
            return

        # 解析数据长度
        data_length = int.from_bytes(self._buffer[3:5], byteorder='big')
        total_length = 8 + data_length

        if len(self._buffer) >= total_length:
            # 提取完整数据包
            packet = bytes(self._buffer[:total_length])
            del self._buffer[:total_length]
            self._handle_received_data(packet)

    def get_connection_info(self) -> dict:
        """获取连接信息"""
        return {
            'interface': 'RS232',
            'port': self.port,
            'baud_rate': self.baud_rate,
            'data_bits': self.data_bits,
            'stop_bits': self.stop_bits,
            'parity': self.parity,
            'flow_control': self.flow_control,
            'is_connected': self.is_connected
        }